package org.bim.view.drag.design.util;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.bim.view.drag.design.model.BaseCondition;
import org.bim.view.drag.design.model.Page;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * `* 描述：分页转换
 * Created by bim view on 2019/1/19.
 */
public class PageUtil {

    /**
     * PageInfo 转 Page
     *
     * @param page pageInfo
     * @param <T>  泛型
     * @return http.Page
     */
    public static <T> Page<T> transform(PageInfo<T> page) {
        Page<T> result = new Page<>();
        result.setPageNum(page.getPageNum());
        result.setPageSize(page.getPageSize());
        result.setTotal(page.getTotal());
        result.setPageTotal(page.getPages());
        result.setList(page.getList());
        return result;
    }

    /**
     * List转Page
     *
     * @param list     list，指的是所有数据
     * @param pageNum  分页参数
     * @param pageSize 分页参数
     * @param <T>      泛型
     * @return page
     */
    public static <T> Page<T> transform(List<T> list, int pageNum, int pageSize) {
        List<T> result = new ArrayList<>();
        int size = list.size();
        if (size <= pageSize) {
            if (pageNum > 1) {
                return new Page<>(result, (long) size, pageNum, pageSize, 1);
            }
            return new Page<>(list, (long) size, pageNum, pageSize, 1);
        } else {
            int pageTotal = size / pageSize + 1;
            //起始页码
            int start = (pageNum - 1) * pageSize;
            if (start + pageSize - 1 < size - 1) {
                for (int i = start; i < start + pageSize; i++) {
                    result.add(list.get(i));
                }
            } else {
                for (int i = start; i < size; i++) {
                    result.add(list.get(i));
                }
            }
            return new Page<>(result, (long) size, pageNum, pageSize, pageTotal);
        }
    }

    /**
     * 构造Page对象
     *
     * @param condition 条件
     * @param supplier  提供列表数据，你应该在其中执行一次且仅一次数据库的列表查询
     * @param <T>
     * @return
     */
    public static <T> Page<T> doPage(BaseCondition condition, Supplier<List<T>> supplier) {
        try (final com.github.pagehelper.Page<Object> page = PageHelper.startPage(condition.getPageNum(), condition.getPageSize())) {
            // doubt：
            //  这里应当要拿到fun.get 返回数据，而又要避免重复执行。
            //  但是doSelectPageInfo内部会执行一次fun，而其中的select.doSelect() 又没有显式的操作返回数据。这里没理解
            return transform(page.doSelectPageInfo(supplier::get));
        }
    }

    /**
     * 构造Page对象，比{@link #doPage(BaseCondition, Supplier)}多一个转换的入参
     *
     * @param condition 条件
     * @param supplier  提供列表数据
     * @param function  提供列表数据转换
     * @param <T>
     * @param <V>
     * @return
     */
    public static <T, V> Page<V> doPage(BaseCondition condition, Supplier<List<T>> supplier, Function<List<T>, List<V>> function) {
        Page<T> page = doPage(condition, supplier);
        return condition.transPage(function.apply(page.getList()), page.getTotal());
    }
}
